package com.joysuch.wwyt.attendant.service.impl;

import cn.hutool.http.HttpRequest;
import cn.zlg.common.util.CollectionUtils;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.reflect.TypeToken;
import com.joysuch.wwyt.attendant.bean.vo.PersonStayTimeReq;
import com.joysuch.wwyt.attendant.bean.vo.PersonStayTimeResp;
import com.joysuch.wwyt.attendant.bean.vo.RailReqVo;
import com.joysuch.wwyt.attendant.bean.vo.V3TokenResp;
import com.joysuch.wwyt.attendant.constant.PlatformConstant;
import com.joysuch.wwyt.attendant.service.OpenPlatformService;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiCoreException;
import com.joysuch.wwyt.core.repository.BaseConfigDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.log.service.ApiLogService;
import com.joysuch.wwyt.util.GsonUtils;
import com.joysuch.wwyt.util.Md5Util;
import com.joysuch.wwyt.workflow.api.bean.Result;
import com.joysuch.wwyt.workflow.api.bean.ResultDataList;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * @author xsx
 * @version 1.0
 * @date 2023/2/20 14:09
 */
@Service
@Slf4j
public class OpenPlatformServiceImpl implements OpenPlatformService {

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private BaseConfigService baseConfigService;

    @Autowired
    private BaseConfigDao baseConfigDao;
    @Autowired
    private ApiLogService apiLogService;

    @Override
    public V3TokenResp getV3TokenResp() throws ApiCoreException {
        Long tenentId = Context.getCurrentTenantId();
        String orgCode = Context.getCompanyCode();
        return getV3TokenResp(tenentId, orgCode);
    }

    @Override
    public V3TokenResp getV3TokenResp(Long tenentId,String orgCode) throws ApiCoreException {

        String redisKey = String.format(BaseConfigCodes.OPEN_SERVICE_V3_TOKEN_REDIS_KEY, tenentId, orgCode);
        String refreshRedisKey = String.format(BaseConfigCodes.OPEN_SERVICE_V3_REFRESH_TOKEN_REDIS_KEY, tenentId, orgCode);
        String signIdKey = String.format(BaseConfigCodes.OPEN_SERVICE_SIGNID_REDIS_KEY, tenentId, orgCode);
        String token = redisClient.get(redisKey);
        String signId = redisClient.get(signIdKey);
        String refreshRedis = redisClient.get(signIdKey);
        V3TokenResp resp = new V3TokenResp();
        if (StringUtils.isNotEmpty(token) && StringUtils.isNotEmpty(signId)) {
            resp.setAccessToken(token);
            resp.setSignId(signId);
            return resp;
        } else if (StringUtils.isNotBlank(refreshRedis)) {
            resp = this.getV3OpenServiceRefreshToken(tenentId, orgCode, refreshRedisKey);
            token = resp.getAccessToken();
            signId = resp.getSignId();
        } else {
             resp = this.getV3OpenServiceToken(tenentId, orgCode);
            token = resp.getAccessToken();
            signId = resp.getSignId();
            String refreshToken = resp.getRefreshToken();
            redisClient.setEx(refreshRedisKey, refreshToken, resp.getExpireAt(), TimeUnit.MILLISECONDS);
        }
        if (StringUtils.isNotEmpty(token)) {
            redisClient.setEx(redisKey, token, 100, TimeUnit.MINUTES);
        }
        if (StringUtils.isNotEmpty(signId)) {
            redisClient.setEx(signIdKey, signId, 100, TimeUnit.MINUTES);
        }
        return resp;
    }

    @Override
    public String syncArea(RailReqVo reqVo) throws ApiCoreException {
        Long tenentId = Context.getCurrentTenantId();
        String orgCode = Context.getCompanyCode();
        BaseConfig ipConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        BaseConfig buildIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        V3TokenResp resp = getV3TokenResp();

        String ipPort = ipConfig.getValue();
        String apiUrl = PlatformConstant.getRailAddUrl;
        String tempUrl;
        String finalUrl;
        if (!ipPort.contains("http")) {
            tempUrl = "http://%s%s";
            finalUrl = String.format(tempUrl, ipPort, apiUrl);
        } else {
            tempUrl = ipPort + "%s";
            finalUrl = String.format(tempUrl, apiUrl);
        }
        String accessToken = resp.getAccessToken();
        String signId = resp.getSignId();
        Long timestamp=  System.currentTimeMillis();
        String xToken = getXToken(accessToken, signId, timestamp);
        JSONObject jsonObject;
        try {
            String response = HttpRequest.post(finalUrl).body(JSONObject.toJSONString(reqVo))
                    .header("X-BuildId", buildIdConfig.getValue())
                    .header("X-RequestId", UUID.randomUUID().toString())
                    .header("X-Timestamp",  timestamp+"")
                    .header("X-SignId", signId)
                    .header("X-Token",xToken ).execute().body();
            jsonObject = JSONObject.parseObject(response);
        } catch (Exception e) {
            throw new ApiCoreException(20030, "操作异常，请检查开放平台服务或配置地址是否正常");
        }
        if (jsonObject != null && 0==jsonObject.getInteger("errorCode")) {
            return jsonObject.getString("data");
        } else {
            return null;
        }
    }

    @Override
    public void updateSyncArea(RailReqVo reqVo) throws ApiCoreException {
        Long tenentId = Context.getCurrentTenantId();
        String orgCode = Context.getCompanyCode();
        BaseConfig ipConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        BaseConfig buildIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        V3TokenResp resp = getV3TokenResp();

        String ipPort = ipConfig.getValue();
        String apiUrl = PlatformConstant.getRailEditUrl;
        String tempUrl;
        String finalUrl;
        if (!ipPort.contains("http")) {
            tempUrl = "http://%s%s";
            finalUrl = String.format(tempUrl, ipPort, apiUrl);
        } else {
            tempUrl = ipPort + "%s";
            finalUrl = String.format(tempUrl, apiUrl);
        }
        String accessToken = resp.getAccessToken();
        String signId = resp.getSignId();
        Long timestamp=  System.currentTimeMillis();
        String xToken = getXToken(accessToken, signId, timestamp);
        String response = HttpRequest.post(finalUrl).body(JSONObject.toJSONString(reqVo))
                .header("X-BuildId", buildIdConfig.getValue())
                .header("X-RequestId", UUID.randomUUID().toString())
                .header("X-Timestamp",  timestamp+"")
                .header("X-SignId", signId)
                .header("X-Token",xToken ).execute().body();
        JSONObject jsonObject = JSONObject.parseObject(response);

    }

    @Override
    public Boolean deleteArea(String platformAreaId) throws ApiCoreException {
        Long tenentId = Context.getCurrentTenantId();
        String orgCode = Context.getCompanyCode();
        BaseConfig ipConfig = baseConfigService.findConfig(tenentId, orgCode, BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        BaseConfig buildIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        V3TokenResp resp = getV3TokenResp();

        String ipPort = ipConfig.getValue();
        String apiUrl = PlatformConstant.getRailDeleteUrl;
        String tempUrl;
        String finalUrl;
        if (!ipPort.contains("http")) {
            tempUrl = "http://%s%s";
            finalUrl = String.format(tempUrl, ipPort, apiUrl);
        } else {
            tempUrl = ipPort + "%s";
            finalUrl = String.format(tempUrl, apiUrl);
        }
        String accessToken = resp.getAccessToken();
        String signId = resp.getSignId();
        Long timestamp=  System.currentTimeMillis();
        String xToken = getXToken(accessToken, signId, timestamp);
        Map<String,String> parm=new HashMap<>();
        parm.put("uuid",platformAreaId);
        String response = HttpRequest.post(finalUrl).body(JSONObject.toJSONString(parm))
                .header("X-BuildId", buildIdConfig.getValue())
                .header("X-RequestId", UUID.randomUUID().toString())
                .header("X-Timestamp",  timestamp+"")
                .header("X-SignId", signId)
                .header("X-Token",xToken ).execute().body();
        JSONObject jsonObject = JSONObject.parseObject(response);
        if (0==jsonObject.getInteger("errorCode")) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    public List<PersonStayTimeResp> railStayTime(PersonStayTimeReq req,Long tenentId,String orgCode) throws ApiCoreException {
        BaseConfig ipConfig = baseConfigDao.findFirstByCodeNative(BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        BaseConfig buildIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        V3TokenResp resp = getV3TokenResp(tenentId,orgCode);

        String ipPort = ipConfig.getValue();
        String apiUrl = PlatformConstant.getRailStayTimeUrl;
        String tempUrl;
        String finalUrl;
        if (!ipPort.contains("http")) {
            tempUrl = "http://%s%s";
            finalUrl = String.format(tempUrl, ipPort, apiUrl);
        } else {
            tempUrl = ipPort + "%s";
            finalUrl = String.format(tempUrl, apiUrl);
        }
        String accessToken = resp.getAccessToken();
        String signId = resp.getSignId();
        Long timestamp=  System.currentTimeMillis();
        String xToken = getXToken(accessToken, signId, timestamp);
        log.info(">>>>>>>> 获取标签围栏停留时长参数: " + JSONObject.toJSONString(req));
        String requestId = UUID.randomUUID().toString();
        String response = HttpRequest.post(finalUrl).body(JSONObject.toJSONString(req))
                .header("X-BuildId", buildIdConfig.getValue())
                .header("X-RequestId", requestId)
                .header("X-Timestamp",  timestamp+"")
                .header("X-SignId", signId)
                .header("X-Token",xToken ).execute().body();
        ResultDataList<PersonStayTimeResp> result = GsonUtils.fromJson(response, new TypeToken<ResultDataList<PersonStayTimeResp>>() {
        }.getType());
        apiLogService.saveApiLog(finalUrl, null, null, null, JSONObject.toJSONString(req), response, Status.SUCCESS.getCode(), requestId);
        if (result.getErrorCode() == Result.SUCCESS && CollectionUtils.isNotEmpty(result.getData())) {
            return result.getData();
        } else {
            if (!org.springframework.util.CollectionUtils.isEmpty(result.getErrorMsg())) {
                log.error("获取标签围栏停留时长错误 code: " + result.getErrorCode() + " errorMessage:" + result.getErrorMsg());
            }
        }
        return null;
    }

    public static String getXToken(String accessToken, String signId, Long
            timestamp){
        return Md5Util.md5(accessToken + Md5Util.md5(signId +
                Md5Util.md5(accessToken)).toLowerCase()+ timestamp).toLowerCase();
    }

    public V3TokenResp getV3OpenServiceToken(Long tenentId, String orgCode) throws ApiCoreException {
        BaseConfig ipConfig = baseConfigDao.findFirstByCodeNative(BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        BaseConfig secretConfig = baseConfigDao.findFirstByCodeNative( BaseConfigCodes.LOCATE_SERVER_SECRET);
        if (ipConfig != null && secretConfig != null) {
            String finalUrl;
            String ipPort = ipConfig.getValue();
            String loginSecret = secretConfig.getValue();
            String apiUrl = PlatformConstant.getAccessTokenUrl;
            //默认http
            Map<String, Object> param = new HashMap<>();
            param.put("licence", loginSecret);
            String tempUrl;
            String response;
            if (!ipPort.contains("http")) {
                tempUrl = "http://%s%s";
                finalUrl = String.format(tempUrl, ipPort, apiUrl);
            } else {
                tempUrl = ipPort + "%s";
                finalUrl = String.format(tempUrl, apiUrl);
            }
            Result<V3TokenResp> result;
            try {
                response = HttpRequest.post(finalUrl).body(JSONObject.toJSONString(param)).execute().body();
                result = GsonUtils.fromJson(response, new TypeToken<Result<V3TokenResp>>() {
                }.getType());
            } catch (Exception e) {
                throw new ApiCoreException(20030, "操作异常，请检查开放平台服务或配置地址是否正常");
            }
            if (result != null && result.getErrorCode() == Result.SUCCESS && result.getData() != null) {
                log.info("open service licence获取的token: tempUrl{}, loginSecret{},token{}", tempUrl, loginSecret, result.getData().getAccessToken());
                apiLogService.saveApiLog(finalUrl, null, null, null, JSONObject.toJSONString(param), response, Status.SUCCESS.getCode(), null);
                return result.getData();
            } else {
                apiLogService.saveApiLog(finalUrl, null, null, null, JSONObject.toJSONString(param), response, Status.FAILED.getCode(), null);
            }
        } else {
            log.info("getPersonTrajectoryPoints Configuration missing, please check");
            throw new ApiCoreException(Status.PERSON_TRAJECTORY_ERROR);
        }
        return null;
    }

    public V3TokenResp getV3OpenServiceRefreshToken(Long tenentId, String orgCode, String refreshToken) throws ApiCoreException {
        BaseConfig ipConfig = baseConfigDao.findFirstByCodeNative(BaseConfigCodes.OPEN_SERVICE_SERVER_URL);
        if (ipConfig != null) {
            String finalUrl;
            String ipPort = ipConfig.getValue();
            String apiUrl = PlatformConstant.getRefreshAccessTokenUrl;
            //默认http
            Map<String, Object> param = new HashMap<>();
            param.put("refreshToken", refreshToken);
            String tempUrl;
            String response;
            if (!ipPort.contains("http")) {
                tempUrl = "http://%s%s";
                finalUrl = String.format(tempUrl, ipPort, apiUrl);
            } else {
                tempUrl = ipPort + "%s";
                finalUrl = String.format(tempUrl, apiUrl);
            }
            response = HttpRequest.post(finalUrl).body(JSONObject.toJSONString(param)).execute().body();
            Result<V3TokenResp> result = GsonUtils.fromJson(response, new TypeToken<Result<V3TokenResp>>() {
            }.getType());
            if (result.getErrorCode() == Result.SUCCESS && result.getData() != null) {
                log.info("open service licence获取的token: tempUrl{}, refreshToken{},token{}", tempUrl, refreshToken, result.getData().getAccessToken());
                apiLogService.saveApiLog(finalUrl, null, null, null, JSONObject.toJSONString(param), response, Status.SUCCESS.getCode(), null);
                return result.getData();
            } else {
                apiLogService.saveApiLog(finalUrl, null, null, null, JSONObject.toJSONString(param), response, Status.FAILED.getCode(), null);
            }
        } else {
            log.info("getPersonTrajectoryPoints Configuration missing, please check");
            throw new ApiCoreException(Status.PERSON_TRAJECTORY_ERROR);
        }
        return null;
    }


}
